import net.sf.json.JSONObject;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.w3c.dom.*;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.*;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Parser {

    private String CLASS_NAME = "Parser";
    private static Map<String, String> preDataMap = null;
    private static Map<String, String> dataMap = null;
    private static Map<String, String> regexMap = null;
    private static boolean unexcuteotherwise = false;
    private static boolean hasotherwise = false;
    private static boolean isBreak = false;
    private boolean recognize = true;
    private static Logger logger = null;

    static
    {
//        PropertyConfigurator.configure("D:\\WorkSpace-IDE\\parser\\src\\main\\java\\log4j2.xml");
//        DOMConfigurator.configure("D:\\WorkSpace-IDE\\parser\\src\\main\\java\\log4j2.xml");
        logger  =  Logger.getLogger(Parser.class);
    }

    public void preParser()
    {
        try {
            preDataMap = new HashMap<String, String>();
            dataMap = new HashMap<String, String>();
            getRegexMap("D:/WorkSpace-IDE/parser/src/main/resources/xml/GeneralPatternDefinitions.xml");
        } catch (Exception e) {
            logger.error(e);
        }
    }

    public Map<String, String> parse(String xmlStr, String fileName)
    {
        try {
            if(StringUtils.isEmpty(xmlStr))
            {
                DocumentBuilderFactory docbf = DocumentBuilderFactory.newInstance();
                DocumentBuilder docb = docbf.newDocumentBuilder();
//                StringReader sr = new StringReader(xmlStr);
//                InputSource is = new InputSource(sr);
                Document doc = docb.parse(new File("D:/WorkSpace-IDE/parser/src/main/resources/xml/" + fileName));
                Element element = doc.getDocumentElement();
                NodeList nodes = element.getChildNodes();
                preParser();
                if(recognize)
                {
                    for(int i=0; i<nodes.getLength(); i++)
                    {
                        Node subNode = nodes.item(i);
                        if(subNode.getNodeType() == Node.ELEMENT_NODE)
                        {
                            Class clazz = Class.forName(CLASS_NAME);
                            String method = getRealMethodName(subNode.getNodeName());
                            clazz.getMethod(method, Node.class).invoke(clazz.newInstance(), subNode);
                        }
                    }
                } else
                {
                    System.out.println("数据不匹配，直接返回！");
                }
            }
        } catch (Exception e) {
            logger.error(e);
        }
        return dataMap;
    }

    public void deviceType(Node node)
    {
        try {
            commonType(node);
        } catch (Exception e) {
            logger.error(e);
        }
    }

    public void appType(Node node)
    {
        try {
            commonType(node);
        } catch (Exception e) {
            logger.error(e);
        }
    }

    public void attachedDeviceType(Node node)
    {
        try {
            commonType(node);
        } catch (Exception e) {
            logger.error(e);
        }
    }

    public void testEvents(Node node)
    {
        NodeList nodes = node.getChildNodes();
        Node subNode = nodes.item(1);
        if(subNode.getNodeType() == Node.ELEMENT_NODE)
        {
            dataMap.put("_rawmsg", subNode.getTextContent().trim());
        }
    }

    public void commonType(Node node) throws Exception
    {
        try {
            NodeList nodes = node.getChildNodes();
            for(int i=0; i<nodes.getLength(); i++)
            {
                Node subNode = nodes.item(i);
                if(subNode.getNodeType() == Node.ELEMENT_NODE)
                {
    //                System.out.println(node.getNodeName() + ": " + subNode.getNodeName()+" "+subNode.getTextContent());
                    dataMap.put(subNode.getNodeName(), subNode.getTextContent().trim());
                }
            }
        } catch (DOMException e) {
            logger.error(e);
        }
    }

    public void patternDefinitions(Node node)
    {
        NodeList nodes = node.getChildNodes();
        try {
            for(int i=0; i<nodes.getLength(); i++)
            {
                Node subNode = nodes.item(i);
                if(subNode.getNodeType() == Node.ELEMENT_NODE)
                {
                    String key = subNode.getAttributes().getNamedItem("name").getNodeValue();
                    if(regexMap.isEmpty() || !regexMap.containsKey(key))
                    {
                        regexMap.put(key, subNode.getTextContent().trim());
                    } else
                    {
                        regexMap.put(key, regexMap.get(key) + subNode.getTextContent().trim());
                    }
//                System.out.println("联合正则表达式：" + nodes.item(i).getNodeName() + " " + nodes.item(i).getAttributes().getNamedItem("name").getNodeValue() + " " + nodes.item(i).getTextContent().trim());
                }
            }
        }catch (Exception e)
        {
            logger.error(e);
        }
    }

    public boolean eventFormatRecognizer(Node node)
    {
        boolean b = false;
        try {
            NodeList nodes = node.getChildNodes();
            for(int i=0; i<nodes.getLength(); i++)
            {
                Node subNode = nodes.item(i);
                if(subNode.getNodeType() == Node.ELEMENT_NODE)
                {
                    System.out.println("eventFormatRecognizer: " + subNode.getAttributes().getNamedItem("name").getNodeName()+" "+subNode.getNodeValue());
                    if(node != null)
                    {
                        if(!StringUtils.isEmpty(subNode.getTextContent().trim()))
                        {
                            b = isRecognize(subNode.getTextContent().trim(), node);
                        }
                    }
                }
            }
        } catch (DOMException e) {
            logger.error(e);
        }
        return b;
    }

    public void parsingInstructions(Node node)
    {
        try {
            NodeList nodes = node.getChildNodes();
            for(int i=0; i<nodes.getLength(); i++)
            {
                Node subNode = nodes.item(i);
                if(subNode.getNodeType() == Node.ELEMENT_NODE)
                {
//                    System.out.println("parsingInstructions: "+subNode.getNodeName());
                    Class clazz = Class.forName(CLASS_NAME);
                    String method = getRealMethodName(subNode.getNodeName());
                    clazz.getMethod(method, Node.class).invoke(clazz.newInstance(), subNode);
                }
            }
        } catch (Exception e) {
            logger.error(e);
        }
    }

    public Map<String, String> getRegexMap(String xmlPath) throws Exception
    {
        try {
            DocumentBuilderFactory docb = DocumentBuilderFactory.newInstance();
            DocumentBuilder doc = docb.newDocumentBuilder();
//          StringReader sr = new StringReader(xmlStr);
//          InputSource is = new InputSource(sr);
            Document regDoc = doc.parse(new File(xmlPath));
            XPathFactory xPathFactory = XPathFactory.newInstance();
            XPath xPath = xPathFactory.newXPath();
            XPathExpression xpExpr = xPath.compile("//pattern");
            Object result = xpExpr.evaluate(regDoc, XPathConstants.NODESET);
            NodeList nodes = (NodeList)result;
            if(nodes.getLength() > 0)
            {
                regexMap = new HashMap<String, String>();
            }
            for(int i=0; i<nodes.getLength(); i++)
            {
                String key = nodes.item(i).getAttributes().getNamedItem("name").getNodeValue();
                if(regexMap.isEmpty() || !regexMap.containsKey(key))
                {
                    regexMap.put(key, nodes.item(i).getTextContent().trim());
                } else
                {
                    regexMap.put(key, regexMap.get(key) + nodes.item(i).getTextContent().trim());
                }
    //                    System.out.println("Pattern: "+key + " " + nodes.item(i).getTextContent().trim());
            }
        } catch (Exception e) {
            logger.error(e);
        }
        return regexMap;
    }

    public boolean isRecognize(String testEvent, Node node)
    {
        boolean b = false;
        try {
            String regexKey = "(<_[^>]*:)";
            Pattern p = Pattern.compile(regexKey);
            String regexNode = node.getTextContent().trim();
            Matcher m = p.matcher(regexNode);
            if(m.find())
            {
                regexNode = common(node);
            }
            String regex = str2Regex(regexNode, regexMap);
            p = Pattern.compile(regex);
            m = p.matcher(testEvent);
            if(!b)
            {
                b = m.find();
            }
        } catch (Exception e) {
            logger.error(e);
        }
        return b;
    }

    public boolean matcher(Node node)
    {
        boolean b = false;
        Matcher m = null;
        try {
            String regexKey = "(<[^>]*:)";
            Pattern p = Pattern.compile(regexKey);
            String regexNode = node.getTextContent().trim();
            m = p.matcher(regexNode);
            List<String> keyList = new ArrayList();
            while (m.find())
            {
                keyList.add(m.group().replaceAll("<|:", ""));
            }
            StringBuffer stringBuffer = new StringBuffer();
            for(String str: keyList)
            {
                if(!StringUtils.isEmpty(str))
                {
                    stringBuffer.append(str+"|");
                }
            }
            String regexStr = stringBuffer.toString();
            if(regexStr.length() > 0)
            {
                regexStr = regexStr.substring(0, regexStr.length()-1);
            }
//        System.out.println("regexStr: "+regexStr);
            regexNode = str2Regex(regexNode.replaceAll(regexStr, ""), regexMap);
            p = Pattern.compile(regexNode);
            String mapKey = node.getAttributes().getLength()==0? "_rawmsg": ParserHelper.trim(node.getAttributes().item(0).getNodeValue());
            m = p.matcher(dataMap.get(mapKey) + "");
            b = m.find();
        } catch (DOMException e) {
            logger.error(e);
        }
        return b;
    }

    public String common(Node node) throws Exception
    {
        //这里的处理方式有两种，这种事凡是匹配上的都保存，如果去除这部分，只会保存有赋值的部分，如：_time:gPatTime
        String regexKey = "(<[^>]*>)";
        String regexNode = "";
        try {
            regexNode = node.getTextContent().trim();
            Pattern p = Pattern.compile(regexKey);
            Matcher m = p.matcher(regexNode);
            List<String> keyList = new ArrayList();
            while (m.find())
            {
                String key = m.group();
                int len = (key.indexOf(":")-key.indexOf("<"));
                if(len>1)
                {
                    key = key.substring(1, len);
                } else
                {
                    key = key.substring(len+1, key.length()-1);
                }
                keyList.add(key);
            }
//        System.out.println("keyList: "+keyList);

            String regexRep = "(<[^>]*:)";
            p = Pattern.compile(regexRep);
            m = p.matcher(regexNode);
            List<String> repList = new ArrayList();
            while (m.find())
            {
                String key = m.group();
                repList.add(key.replaceAll("<|:", ""));
            }

            StringBuffer stringBuffer = new StringBuffer();
            for(String str: repList)
            {
                if(!StringUtils.isEmpty(str))
                {
                    stringBuffer.append(str+"|");
                }
            }
//        System.out.println("repList: " + repList);
            String regexStr = stringBuffer.toString();
            if(regexStr.length() > 0)
            {
                regexStr = regexStr.substring(0, regexStr.length()-1);
            }
//        System.out.println("regexStr: "+regexStr);
            regexNode = str2Regex(regexNode.replaceAll(regexStr, ""), regexMap);
            p = Pattern.compile(regexNode);
            String mapKey = node.getAttributes().getLength()==0? "_rawmsg": ParserHelper.trim(node.getAttributes().item(0).getNodeValue());
            m = p.matcher(dataMap.get(mapKey) + "");
//            System.out.println("regexNode: "+regexNode);

            while (m.find())
            {
                for(int i=1; i<=m.groupCount(); i++)
                {
    //                if(!StringUtils.isEmpty(keyList.get(i - 1)))
    //                {
    //                System.out.println(keyList.get(i-1)+": " +m.group(i));
                        dataMap.put(keyList.get(i - 1), m.group(i));
    //                }
                }
            }
        } catch (DOMException e) {
            logger.error(e);
        }
        return regexNode;
    }

    public String str2Regex(String oldStr, Map<String, String> regexMap)
    {
//        System.out.println(oldStr);
        try {
            if(!regexMap.isEmpty())
            {
                for(Iterator<Map.Entry<String, String>> iter = regexMap.entrySet().iterator(); iter.hasNext();)
                {
                    Map.Entry<String, String> entry = iter.next();
                    oldStr = oldStr.replace("<:" + entry.getKey() + ">", "(" + entry.getValue() + ")");
                }
            }
        } catch (Exception e) {
            logger.error(e);
        }
//        System.out.println(oldStr);
        return oldStr.trim();
    }

    public void collectFieldsByRegex(Node node)
    {
        try {
            if(matcher(node))
            {
                common(node);
                isBreak = true;//执行switchcase语法
            }
        } catch (Exception e) {
            logger.error(e);
        }
    }

    public void collectAndSetAttrByRegex(Node node)
    {
        try {
            if(matcher(node))
            {
                common(node);
                isBreak = true;//执行switchcase语法
            }
        } catch (Exception e) {
            logger.error(e);
        }
    }

    public void collectAndSetAttrByPosWithNestedSep(Node node)
    {
        String splitRegex = "";
        String combineRegex = "";
        String $_body = "";
        try {
            int count = node.getAttributes().getLength();
            for(int i=0; i<count; i++)
            {
                String attrName = node.getAttributes().item(i).getNodeName();
                String attrVal = node.getAttributes().item(i).getNodeValue();
                if("L1Sep".equals(attrName))
                {
                    splitRegex = attrVal;
                }
                if("L2Sep".equals(attrName))
                {
                    combineRegex = attrVal;
                }
                if("src".equals(attrName))
                {
                    $_body = dataMap.get(ParserHelper.trim(attrVal)) + "";
                }
            }
            String[] bodyArr = $_body.split(splitRegex);
//        System.out.println(Arrays.asList(bodyArr).size());
//        System.out.println(Arrays.asList(bodyArr));
            List<String> bodyList = new ArrayList<String>();
            if(combineRegex.length() == 2)
            {
                String start = combineRegex.charAt(0)+"";
                String end = combineRegex.charAt(1)+"";
                String newStr = "";
                int newIndex = -1;
                boolean isCombine = false;
                for(String str: bodyArr)
                {
                    if(str.indexOf(start)==0
                            && str.lastIndexOf(end)!=str.length())
                    {
                        if(newIndex == -1)
                        {
                            //找到要拼接的初始位置并且开始执行拼接
                            newIndex = ArrayUtils.indexOf(bodyArr, str);
                            isCombine = true;
                        }
                    }
                    if(!isCombine)
                    {
                        bodyList.add(str);
                    }
                    //拼接结束
                    if(str.indexOf(start)!=0
                            && str.lastIndexOf(end)==str.length()-1)
                    {
                        newStr += " " + str;
                        isCombine = false;
                        bodyList.add(newIndex, newStr);
                    }
                    if(isCombine)
                    {
                        newStr += " " + str;
                    }
                }
                System.out.println("bodyList: "+ bodyList);
            }
            NodeList nodeList = node.getChildNodes();
            for(int i=0; i<nodeList.getLength(); i++)
            {
                Node subNode = nodeList.item(i);
                if(subNode.getNodeType() == Node.ELEMENT_NODE)
                {
                    count = subNode.getAttributes().getLength();
                    String key = "";
                    String val = "";
                    for(int j=0; j<count; j++)
                    {
                        String attrName = subNode.getAttributes().item(j).getNodeName();
                        String attrVal = subNode.getAttributes().item(j).getNodeValue();
                        if("attr".equals(attrName))
                        {
                            key = attrVal;
                        }
                        if("pos".equals(attrName))
                        {
                            int index = Integer.valueOf(attrVal);
                            val = bodyList.get(index-1);
                            dataMap.put(key, val);
                        }
                    }
                }
            }
        } catch (DOMException e) {
            logger.error(e);
        } catch (NumberFormatException e) {
            logger.error(e);
        }
    }

    public void collectAndSetAttrByPos(Node node)
    {
        String splitRegex = "";
        String $_body = "";
        try {
            int count = node.getAttributes().getLength();
            for(int i=0; i<count; i++)
            {
                String attrName = node.getAttributes().item(i).getNodeName();
                String attrVal = node.getAttributes().item(i).getNodeValue();
                if("sep".equals(attrName))
                {
                    splitRegex = attrVal;
                }
                if("src".equals(attrName))
                {
                    $_body = dataMap.get(ParserHelper.trim(attrVal)) + "";
                }
            }
//        System.out.println("$_body: " + $_body);
            String[] bodyArr = $_body.split(splitRegex);
//        String[] bodyArr = StringUtils.join($_body.split(splitRegex)).split("\\|");//之前写的，不记得是针对哪一个xml写的了
//        System.out.println(Arrays.asList(bodyArr).size());
//        System.out.println(Arrays.asList(bodyArr));
            NodeList nodeList = node.getChildNodes();
            for(int i=0; i<nodeList.getLength(); i++)
            {
                Node subNode = nodeList.item(i);
                if(subNode.getNodeType() == Node.ELEMENT_NODE)
                {
                    count = subNode.getAttributes().getLength();
                    String key = "";
                    String val = "";
                    for(int j=0; j<count; j++)
                    {
                        String attrName = subNode.getAttributes().item(j).getNodeName();
                        String attrVal = subNode.getAttributes().item(j).getNodeValue();
                        if("attr".equals(attrName))
                        {
                            key = attrVal;
                        }
                        if("pos".equals(attrName))
                        {
                            int index = Integer.valueOf(attrVal);
                            val = bodyArr[index-1];
                            dataMap.put(key, val);
                        }
                    }
                }
            }
        } catch (DOMException e) {
            logger.error(e);
        } catch (NumberFormatException e) {
            logger.error(e);
        }
    }

    public void collectAndSetAttrByKeyValuePair(Node node)
    {
//        System.out.println("collectAndSetAttrByKeyValuePair: " + node.getNodeName());
        String splitRegex = "";
        String $_body = "";
        try {
            int count = node.getAttributes().getLength();
            for(int i=0; i<count; i++)
            {
                String attrName = node.getAttributes().item(i).getNodeName();
                String attrVal = node.getAttributes().item(i).getNodeValue();
                if("sep".equals(attrName))
                {
                    splitRegex = attrVal;
                }
                if("src".equals(attrName))
                {
                    $_body = dataMap.get(ParserHelper.trim(attrVal)) + "";
                }
            }
            System.out.println("pair_$_body: " + $_body);
            NodeList nodeList = node.getChildNodes();
            for(int i=0; i<nodeList.getLength(); i++)
            {
                Node subNode = nodeList.item(i);
                if(subNode.getNodeType() == Node.ELEMENT_NODE)
                {
                    count = subNode.getAttributes().getLength();
                    String key = "";
                    String val = "";
                    for(int j=0; j<count; j++)
                    {
                        String attrName = subNode.getAttributes().item(j).getNodeName();
                        String attrVal = subNode.getAttributes().item(j).getNodeValue();
                        if("attr".equals(attrName))
                        {
                            key = attrVal;
                        }
                        if("key".equals(attrName))
                        {
                            int index = $_body.indexOf(attrVal);
                            if(index >= 0)
                            {
                                index += attrVal.length();
                                int endIndex = $_body.indexOf(splitRegex, index)==-1? $_body.length(): $_body.indexOf(splitRegex, index);
                                val = $_body.substring(index, endIndex);
                            }
                            int oIndex = val.indexOf("\"");
                            if(oIndex == 0 || oIndex == val.length()-1)
                            {
                                val = val.replaceAll("\"", "");
                            }
                            dataMap.put(key, val);
                        }
                    }
                }
            }
        } catch (DOMException e) {
            logger.error(e);
        }
//        System.out.println(JSONObject.fromObject(dataMap).toString(1));
    }

    //老的方法，待删除
    public void oldcollectAndSetAttrByKeyValuePair(Node node)
    {
//        System.out.println("collectAndSetAttrByKeyValuePair: " + node.getNodeName());
        String splitRegex = "";
        String $_body = "";
        try {
            int count = node.getAttributes().getLength();
            for(int i=0; i<count; i++)
            {
                String attrName = node.getAttributes().item(i).getNodeName();
                String attrVal = node.getAttributes().item(i).getNodeValue();
                if("sep".equals(attrName))
                {
                    splitRegex = attrVal;
                }
                if("src".equals(attrName))
                {
                    $_body = dataMap.get(ParserHelper.trim(attrVal)) + "";
                }
            }
            //特殊字符的处理，如|，），（都要预备家\\，以防止报错 暂时没完善
            int sindex = splitRegex.indexOf("(|)");
            String regex1 = "\\\\\\\\";
            String regex2 = "\\\\";
            Pattern p = Pattern.compile("");
            if(sindex >= 0)
            {
                if(Pattern.compile(regex1).matcher(splitRegex).matches())
                {
    //                splitRegex = splitRegex.substring(0, splitRegex.)
                }
                if(Pattern.compile(regex2).matcher(splitRegex).matches())
                {

                }
            }
            System.out.println("pair_$_body: " + $_body);
            String[] bodyArr = $_body.split(splitRegex);
            System.out.println(Arrays.asList(bodyArr).size());
            System.out.println(Arrays.asList(bodyArr));
            NodeList nodeList = node.getChildNodes();
            for(int i=0; i<nodeList.getLength(); i++)
            {
                Node subNode = nodeList.item(i);
                if(subNode.getNodeType() == Node.ELEMENT_NODE)
                {
                    count = subNode.getAttributes().getLength();
                    String key = "";
                    String val = "";
                    for(int j=0; j<count; j++)
                    {
                        String attrName = subNode.getAttributes().item(j).getNodeName();
                        String attrVal = subNode.getAttributes().item(j).getNodeValue();
                        if("attr".equals(attrName))
                        {
                            key = attrVal;
                        }
                        if("key".equals(attrName))
                        {
                            int index = -1;
                            for(String str: bodyArr)
                            {
                                index = str.contains(attrVal)? ArrayUtils.indexOf(bodyArr, str): -1;
                                if(index >= 0)
                                {
                                    val = bodyArr[index].substring(bodyArr[index].indexOf(attrVal)+attrVal.length(), bodyArr[index].length());
                                    break;
                                }
                            }
                            int oIndex = val.indexOf("\"");
                            if(oIndex == 0 || oIndex == val.length()-1)
                            {
                                val = val.replaceAll("\"", "");
                            }
                            dataMap.put(key, val);
                        }
                    }
                }
            }
        } catch (DOMException e) {
            logger.error(e);
        }
//        System.out.println(JSONObject.fromObject(dataMap).toString(1));
    }

    //同collectAndSetAttrByKeyValuePair数据处理一样，可能要改
    public void collectAndSetAttrByKeyValuePairMultiValue(Node node)
    {
        String splitRegex = "";
        String $_body = "";
        try {
            int count = node.getAttributes().getLength();
            for(int i=0; i<count; i++)
            {
                String attrName = node.getAttributes().item(i).getNodeName();
                String attrVal = node.getAttributes().item(i).getNodeValue();
                if("sep".equals(attrName))
                {
                    splitRegex = attrVal;
                }
                if("src".equals(attrName))
                {
                    $_body = dataMap.get(ParserHelper.trim(attrVal)) + "";
                }
            }
            String[] bodyArr = $_body.split(splitRegex);
//        System.out.println(Arrays.asList(bodyArr).size());
//        System.out.println(Arrays.asList(bodyArr));
            NodeList nodeList = node.getChildNodes();
            for(int i=0; i<nodeList.getLength(); i++)
            {
                Node subNode = nodeList.item(i);
                if(subNode.getNodeType() == Node.ELEMENT_NODE)
                {
                    count = subNode.getAttributes().getLength();
                    String key = "";
                    String val = "";
                    for(int j=0; j<count; j++)
                    {
                        String attrName = subNode.getAttributes().item(j).getNodeName();
                        String attrVal = subNode.getAttributes().item(j).getNodeValue();
                        if("attr".equals(attrName))
                        {
                            key = attrVal;
                        }
                        if("key".equals(attrName))
                        {
                            int index = -1;
                            for(String str: bodyArr)
                            {
                                index = str.contains(attrVal)? ArrayUtils.indexOf(bodyArr, str): -1;
                                if(index >= 0)
                                {
                                    val = bodyArr[index].substring(bodyArr[index].indexOf(attrVal)+attrVal.length(), bodyArr[index].length());
                                    break;
                                }
                            }
                            int oIndex = val.indexOf("\"");
                            if(oIndex == 0 || oIndex == val.length()-1)
                            {
                                val = val.replaceAll("\"", "");
                            }
                            dataMap.put(key, val);
                        }
                    }
                }
            }
        } catch (DOMException e) {
            logger.error(e);
        }
//        System.out.println(JSONObject.fromObject(dataMap).toString(1));
    }

    public void setEventAttributeFromXPath(Node node)
    {
        try {
            DocumentBuilderFactory docbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder docb = docbf.newDocumentBuilder();
            StringReader sr = new StringReader(dataMap.get("_rawmsg")+"");
            InputSource is = new InputSource(sr);
            Document doc = docb.parse(is);
            XPathFactory xPathFactory = XPathFactory.newInstance();
            XPath xPath = xPathFactory.newXPath();
            String key = node.getAttributes().getNamedItem("attr").getNodeValue();
            System.out.println(node.getNodeName());
            System.out.println("key: " + key);
            XPathExpression xpExpr = xPath.compile(node.getTextContent());
            Object result = xpExpr.evaluate(doc, XPathConstants.NODE);
            Node val = (Node)result;
            dataMap.put(key, val!=null? val.getNodeValue(): "");
        } catch (ParserConfigurationException e) {
            logger.error(e);
        } catch (SAXException e) {
            logger.error(e);
        } catch (IOException e) {
            logger.error(e);
        } catch (XPathExpressionException e) {
            logger.error(e);
        }
//        System.out.println(JSONObject.fromObject(dataMap).toString(1));
    }

    public void collectAndSetAttrByPosWithQuotes(Node node)
    {
        String splitRegex = "";
        String repalceRegex = "";
        String $_body = "";
        try {
            int count = node.getAttributes().getLength();
            for(int i=0; i<count; i++)
            {
                String attrName = node.getAttributes().item(i).getNodeName();
                String attrVal = node.getAttributes().item(i).getNodeValue();
                if("sep".equals(attrName))
                {
                    splitRegex = attrVal;
                }
                if("quo".equals(attrName))
                {
                    repalceRegex = attrVal;
                }
                if("src".equals(attrName))
                {
                    $_body = dataMap.get(ParserHelper.trim(attrVal)) + "";
                }
            }
            String[] bodyArr = $_body.split(splitRegex);
//        System.out.println(Arrays.asList(bodyArr).size());
//        System.out.println(Arrays.asList(bodyArr));
            NodeList nodeList = node.getChildNodes();
            for(int i=0; i<nodeList.getLength(); i++)
            {
                Node subNode = nodeList.item(i);
                if(subNode.getNodeType() == Node.ELEMENT_NODE)
                {
                    count = subNode.getAttributes().getLength();
                    String key = "";
                    String val = "";
                    for(int j=0; j<count; j++)
                    {
                        String attrName = subNode.getAttributes().item(j).getNodeName();
                        String attrVal = subNode.getAttributes().item(j).getNodeValue();
                        if("attr".equals(attrName))
                        {
                            key = attrVal;
                        }
                        if("pos".equals(attrName))
                        {
                            int index = Integer.valueOf(attrVal);
                            if(index < bodyArr.length)
                            {
                                val = bodyArr[index-1];
                                dataMap.put(key, val!=null?val.replace(repalceRegex, ""): "");
                            }
                        }
                    }
                }
            }
        } catch (DOMException e) {
            logger.error(e);
        } catch (NumberFormatException e) {
            logger.error(e);
        }
    }

    public void collectAndSetAttrBySymbol(Node node)
    {
        String splitRegex = "";
        String symStart = "";
        String symEnd = "";
        String $_body = "";
        try {
            int count = node.getAttributes().getLength();
            for(int i=0; i<count; i++)
            {
                String attrName = node.getAttributes().item(i).getNodeName();
                String attrVal = node.getAttributes().item(i).getNodeValue();
                if("src".equals(attrName))
                {
                    $_body = dataMap.get(ParserHelper.trim(attrVal)) + "";
                }
                if("sep".equals(attrName))
                {
                    splitRegex = attrVal;
                }
                if("symStart".equals(attrName))
                {
                    symStart = attrVal;
                }
                if("symEnd".equals(attrName))
                {
                    symEnd = attrVal;
                }
            }
//        System.out.println("$_body: "+$_body);
            String[] bodyArr = $_body.split(splitRegex);
//        System.out.println(Arrays.asList(bodyArr).size());
//        System.out.println(Arrays.asList(bodyArr));
            NodeList nodeList = node.getChildNodes();
            for(int i=0; i<nodeList.getLength(); i++)
            {
                Node subNode = nodeList.item(i);
                if(subNode.getNodeType() == Node.ELEMENT_NODE)
                {
                    String[] excludeArr = subNode.getTextContent().split(",");
                    for(String str: bodyArr)
                    {
                        int startIndex = str.indexOf(symStart)<0? 0: str.indexOf(symStart)+1;
                        int endIndex = str.indexOf(symEnd);
                        String key = str.substring(startIndex, endIndex);
                        String val = str.substring(endIndex+symEnd.length(), str.length());
                        if(ArrayUtils.indexOf(excludeArr, key)<0)
                        {
                            dataMap.put(key, val);
                        }
                    }
                }
            }
        } catch (DOMException e) {
            logger.error(e);
        }
    }

    public void collectAndSetAttrFromAnotherEvent(Node node)
    {
        try {
            System.out.println("方法暂未实现！");
        } catch (Exception e) {
            logger.error(e);
        }
    }

    public void setEventAttribute(Node node)
    {
        try {
            String attrVal = node.getAttributes().item(0).getNodeValue();
            String nodeVal = node.getTextContent().trim();
            if(nodeVal.contains("("))
            {
                dataMap.put(attrVal, str2Method(nodeVal));
            } else if(nodeVal.contains("$"))
            {
                dataMap.put(attrVal, dataMap.get(ParserHelper.trim(nodeVal)));
            } else
            {
                dataMap.put(attrVal, nodeVal);
            }
        } catch (DOMException e) {
            logger.error(e);
        }
    }

    public void swap(Node node)
    {
        try {
            String[] swapArr = node.getTextContent().split(", |,");
            String firstVal = dataMap.get(swapArr[0]);
            String secondVal = dataMap.get(swapArr[1]);
            if(firstVal!=null && secondVal!=null)
            {
                String curr = firstVal.toString();
                dataMap.put(swapArr[0], secondVal);
                dataMap.put(swapArr[1], curr);
            }
        } catch (DOMException e) {
            logger.error(e);
        }
    }

    public String str2Method(String fullName)
    {
        String result = null;
        try {
            String method = fullName.substring(0, fullName.indexOf("("));
            String paramStr = fullName.substring(fullName.indexOf("(")+1, fullName.lastIndexOf(")"));
            String[] paramArr = paramStr.split(", ");
            result = "";
            for(String str: paramArr)
            {
                int index = Arrays.asList(paramArr).indexOf(str);
                if(str.contains("\""))
                {
                    paramArr[index] = str.replaceAll("\"", "");
                }
                if(str.contains("$"))
                {
                    paramArr[index] = dataMap.get(ParserHelper.trim(str))+"";
                }
            }
//            System.out.println(Arrays.asList(paramArr));
            Class clazz = Class.forName("SetEventAttr");
            result = clazz.getMethod(method, String[].class).invoke(clazz.newInstance(), (Object)paramArr) + "";
        } catch (ClassNotFoundException e) {
            logger.error(e);
        } catch (IllegalAccessException e) {
            logger.error(e);
        } catch (InvocationTargetException e) {
            logger.error(e);
        } catch (NoSuchMethodException e) {
            logger.error(e);
        } catch (InstantiationException e) {
            logger.error(e);
        }
        return result;
    }

    public void when(Node node)
    {
        try {
            if(!whenTest(node.getAttributes().item(0).getNodeValue()))
            {
//            System.out.println(node.getAttributes().item(0).getNodeValue()+" 对不起，你被否决了！");
                return;
            } else
            {
//                System.out.println("when: "+node.getAttributes().item(0).getNodeValue());
//                System.out.println("我通过了！" + hasotherwise);
                if(hasotherwise)//只有otherwise模式开启才会执行
                {
                    unexcuteotherwise = true;
                }
            }
            NodeList nodeList = node.getChildNodes();
            for(int i=0; i<nodeList.getLength(); i++)
            {
                Node subNode = nodeList.item(i);
                if(subNode.getNodeType() == Node.ELEMENT_NODE)
                {
//                    System.out.println(subNode.getNodeName() + " " + subNode.getTextContent().trim());
                    Class clazz = Class.forName(CLASS_NAME);
                    String method = getRealMethodName(subNode.getNodeName());
                    clazz.getMethod(method, Node.class).invoke(clazz.newInstance(), subNode);
                }
            }
        } catch (ClassNotFoundException e) {
            logger.error(e);
        } catch (IllegalAccessException e) {
            logger.error(e);
        } catch (InvocationTargetException e) {
            logger.error(e);
        } catch (NoSuchMethodException e) {
            logger.error(e);
        } catch (InstantiationException e) {
            logger.error(e);
        }
    }

    public void otherwise(Node node)
    {
        try {
            commonMethod(node);
        } catch (Exception e) {
            logger.error(e);
        }
    }

    public boolean whenTest(String condition)
    {
        boolean b = false;
        try {
            if(StringUtils.isEmpty(condition))
            {
                return b;
            }
            if(condition.contains("exist "))
            {
                String paramFirst = condition.substring(condition.indexOf(" ") + 1, condition.length());
                if(condition.contains("not_exist "))
                {
                    b = WhenTestUtils.not_exist(paramFirst, dataMap);
                }
                if(condition.contains("exist "))
                {
                    b = WhenTestUtils.exist(paramFirst, dataMap);
                }

            }
            if(condition.contains(" = "))
            {
                String paramFirst = condition.substring(0, condition.indexOf("=")-1);
                String paramSecond = condition.substring(condition.lastIndexOf(" ")+2, condition.length()-1);
                b = WhenTestUtils.equal(paramFirst, paramSecond, dataMap);
            }
            if(condition.contains(" != "))
            {
                String paramFirst = condition.substring(0, condition.indexOf("!=")-1);
                String paramSecond = condition.substring(condition.indexOf(" ")+2, condition.length()-1);
                b = WhenTestUtils.unequal(paramFirst, paramSecond, dataMap);
            }
            if(condition.contains("matches("))
            {
                String paramFirst = condition.substring(condition.indexOf("(")+1, condition.indexOf(","));
                String paramSecond = "";
                if(condition.contains("'") | condition.contains("\""))
                {
                    paramSecond = condition.substring((condition.indexOf("'")<0?condition.indexOf("\""):condition.indexOf("'"))+1, condition.lastIndexOf(")")-1);
                } else
                {
    //                paramSecond = dataMap.get(condition.substring(condition.indexOf(" ")+1, condition.lastIndexOf(")")));
                    paramSecond = regexMap.get(condition.substring(condition.indexOf(" ")+1, condition.lastIndexOf(")")));
                }
                if(condition.contains("not_matches"))
                {
                    b = WhenTestUtils.not_matches(paramFirst, paramSecond, dataMap);
                }
                if(condition.contains("matches"))
                {
                    b = WhenTestUtils.matches(paramFirst, paramSecond, dataMap);
                }
            }

            if(condition.contains(" IN "))
            {
                String paramFirst = condition.substring(0, condition.indexOf(" IN"));
                String[] paramSecond = condition.substring(condition.indexOf("IN ")+4, condition.length()-1).split(", |,");
                b = WhenTestUtils.in(paramFirst, paramSecond, dataMap);
            }
        } catch (Exception e) {
            logger.error(e);
        }
        return b;
    }

    public void switchCase(Node node)
    {
        isBreak = false;
        try {
            commonMethod(node);
        } catch (Exception e) {
            logger.error(e);
        }
    }

    public void caseMethod(Node node)
    {
        try {
            if(!isBreak)
            {
                commonMethod(node);
            }
        } catch (Exception e) {
            logger.error(e);
        }
    }

    public void defaultMethod(Node node)
    {
        try {
            if(!isBreak)
            {
                commonMethod(node);
            }
        } catch (Exception e) {
            logger.error(e);
        }
    }

    public void choose(Node node)
    {
        try {
            commonMethod(node);
        } catch (Exception e) {
            logger.error(e);
        }
    }

    public void commonMethod(Node node) throws Exception
    {

        try {
            if("choose".equals(node.getNodeName())) {
                hasotherwise = true;//如果为choose节点，就要开启otherwise功能
            }
            NodeList nodeList = node.getChildNodes();
            int count = nodeList.getLength();
            for(int i=0; i<count; i++)
            {
                Node subNode = nodeList.item(i);
                if(subNode.getNodeType() == Node.ELEMENT_NODE)
                {
                    try {
                        Class clazz = Class.forName(CLASS_NAME);
                        String method = getRealMethodName(subNode.getNodeName());
                        if("otherwise".equals(method))
                        {
                            if(!unexcuteotherwise)
                            {
                                clazz.getMethod(method, Node.class).invoke(clazz.newInstance(), subNode);
                            }
                        } else
                        {
                            clazz.getMethod(method, Node.class).invoke(clazz.newInstance(), subNode);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            hasotherwise = false;//该模式执行完毕之后要将其关闭
        } catch (Exception e) {
            logger.error(e);
        }
    }

    public String getRealMethodName(String nodeName)
    {
        if("switch".equals(nodeName))
        {
            nodeName = "switchCase";
        } else if("case".equals(nodeName))
        {
            nodeName = "caseMethod";
        } else if("default".equals(nodeName))
        {
            nodeName = "defaultMethod";
        } else if("default".equals(nodeName))
        {
            nodeName = "defaultMethod";
        }
        return nodeName;
    }

    public static void main(String[] args) throws SAXException, IOException {
        new Parser().parse("", "CiscoPIXParser.xml");
        for (String key : dataMap.keySet()) {
            if (!key.contains("_")) {
                preDataMap.put(key, dataMap.get(key));
            }
        }
        System.out.println(JSONObject.fromObject(dataMap).toString(1));
        System.out.println(JSONObject.fromObject(preDataMap).toString(1));
//        String[] strArr = "<190>109219: Jan  9 18:03:35.281: %FW-6-SESS_AUDIT_TRAIL_START: Start tcp session: initiator (192.168.20.33:1876) -- responder (192.168.0.10:445)".split(",\\[");
//        System.out.println(strArr.length + ": " + Arrays.asList(strArr));
//        System.out.println("(12)autodiscover(8)abc(3)net(0)".replaceAll("\\(\\d+\\)", "."));
//        String str = "<:gPatSyslogPRI>?(?:<:gPatMon>\\s+<:gPatDay>\\s+<:gPatTime>\\s+<_host:gPatStr>\\s+)?<_header:gPatMesgBody>?%<_evIdPrefix:patCiscoIOSMod>(?:-<:gPatStr>)?-<_severity:gPatInt>-<_evIdSuffix:patStrEndColon>: <_body:gPatMesgBody>";
//        String regexKey = "(<[^>]*>)";
//        Pattern p = Pattern.compile(regexKey);
//        Matcher m = p.matcher(str);
//        List<String> keyList = new ArrayList<String>();
//        while (m.find())
//        {
//            String key = m.group();
//            int len = (key.indexOf(":")-key.indexOf("<"));
//            if(len>1)
//            {
//                key = key.substring(1, len);
//            } else
//            {
//                key = key.substring(len+1, key.length()-1);
//            }
//            keyList.add(key);
//        }
//        System.out.println(keyList);
//        String regexKey = "(AVG\\([^(]*\\))";
//        String str = "afadfAVG(12a)adfsdafdAVG(123a)";
//        Pattern p = Pattern.compile(regexKey);
//        Matcher m = p.matcher(str);
//        System.out.println(m.groupCount());
//        while(m.find())
//        {
//            System.out.println(m.group());
//        }

    }
}